package com.project.util;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * 切面类
 */
@Component
@Aspect //申请该类为切面类
public class AspetObj {

    //指定包中的方法执行前，需要执行该方法
    //第一个* 表示方法返回的任意参数
    //com.project.service 为包名 后面如果是.那只包含当前包中的类
    //如果是..表示当前包及子包中所有的类
    //*.* 是指所有类的所有方法
    //(..) 表示方法的任意参数
    @Before("execution(* com.project.service..*.*(..))")
    public void before(){
        System.out.println("前置通知");
    }

    //返回后通知，目标方法正常执行，才会执行
//    @AfterReturning("execution(* com.project.service..*.*(..))")
    //后通知，无论目标方法是否发生异常，都会执行
    @After("execution(* com.project.service..*.*(..))")
    public  void after(){
        System.out.println("返回后通知");
    }

    @Around("execution(* com.project.service..*.d*(..))")
    public Object around(ProceedingJoinPoint point) {
        try {
            System.out.println("环绕前");

            //得到目标对象
            Object target = point.getTarget();
            //执行目标对象的目标方法，得到方法执行后的返回值
            Object returnObj = point.proceed();
            System.out.println("环绕后");
            return returnObj;
        }catch (Throwable e){
            e.printStackTrace();
        }
        return null;
    }

    //抛出异常通知，value表示切面方法应用范围
    // throwing中定义变量（必须和形参同名） 接收方法抛出的异常
    @AfterThrowing(value = "execution(* com.project.service..*.*(..))",
                    throwing = "e")
    public void throwException(JoinPoint point,Exception e){
        //得到目标对象
        Object target = point.getTarget();
        //得到执行方法名
        String methodName = point.getSignature().getName();

        System.out.println("执行"+target.getClass().getName()+"的"+methodName
            +"，抛出"+e.getClass().getSimpleName());
    }
}
